package avicit.bdp.dms.das.service;


import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.service.service.BdpCommonService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.enums.StatusEnums;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dms.das.dao.BusinessDAO;
import avicit.bdp.dms.das.dto.BdpDasBusinessLinkDTO;
import avicit.bdp.dms.das.dto.BdpDasCategoryDTO;
import avicit.bdp.dms.das.dto.BusinessDTO;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/** 
 * 业务对象表服务
 *
 */
@Transactional
@Service
public class BusinessService extends BaseService<BusinessDAO, BusinessDTO> {

    @Autowired
    private BdpDasCategoryService categoryService;
    @Autowired
    private ConvertColumnClient convertColumnClient;
    @Autowired
    private BdpDasBusinessLinkService bdpDasBusinessLinkService;
    @Autowired
    private BdpCommonService bdpCommonService;

    /**
     * 新增业务对象
     * @param businessDTO
     * @return
     */
    public BusinessDTO insertBusiness(BusinessDTO businessDTO) {
        CheckParaUtils.checkIntegerValidity(businessDTO.getType(), logger, "类型必填");
        CheckParaUtils.checkStringValidity(businessDTO.getCategoryId(), logger, "主题必填");
        CheckParaUtils.checkIntegerValidity(businessDTO.getOrderBy(), logger, "排序号必填");

        checkNameUnique(businessDTO);

        businessDTO.setId(ComUtil.getId());
        businessDTO.setStatus(StatusEnums.STOP.getCode());
        businessDTO.setSecretLevel(bdpCommonService.getMinSecretLevel());
        insertSelective(businessDTO);

        BdpLogUtil.log4Insert(businessDTO);
        return businessDTO;
    }

    /**
     * 修改业务对象
     * @param businessDTO
     */
    public void updateBusiness(BusinessDTO businessDTO) {
        CheckParaUtils.checkStringValidity(businessDTO.getName(), logger, "名称必填");
        CheckParaUtils.checkStringValidity(businessDTO.getCategoryId(), logger, "主题必填");
        CheckParaUtils.checkIntegerValidity(businessDTO.getOrderBy(), logger, "排序号必填");

        BusinessDTO oldBusinessDTO = this.selectByPrimaryKey(businessDTO.getId());
        CheckParaUtils.checkDbObjectValidity(oldBusinessDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", businessDTO.getId()));

        if (oldBusinessDTO.getStatus() != null && oldBusinessDTO.getStatus() == StatusEnums.RUNNING.getCode()) {
            throw new BusinessException("该业务对象已启用，不能编辑!");
        }

        // 校验标准名称唯一性
        if (!businessDTO.getName().equals(oldBusinessDTO.getName())) {
            checkNameUnique(businessDTO);
        }

        businessDTO.setCreationDate(oldBusinessDTO.getCreationDate());
        this.updateByPrimaryKey(businessDTO);
        BdpLogUtil.log4Update(businessDTO, oldBusinessDTO);
    }

    /**
     * 删除业务对象
     * @param id
     */
    public void deleteBusiness(String id) {
        CheckParaUtils.checkStringValidity(id, logger, "没有传入待删除的ID");
        BusinessDTO businessDTO = this.selectByPrimaryKey(id);
        CheckParaUtils.checkDbObjectValidity(businessDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", id));
        if (businessDTO.getStatus() != null && businessDTO.getStatus() == StatusEnums.RUNNING.getCode()) {
            throw new BusinessException("该业务对象已启用，不能删除!");
        }
        this.mapper.deleteByPrimaryKey(id);
        //删除线
        bdpDasBusinessLinkService.deleteLinkByBusinessId(id);
        // 记录日志
        BdpLogUtil.log4Delete(businessDTO);
    }

    /**
     * 校验名称唯一性
     *
     * @param businessDTO 检测对象
     */
    private void checkNameUnique(BusinessDTO businessDTO) {
        if (businessDTO != null) {
            if (StringUtils.isEmpty(businessDTO.getName())) {
                throw new BusinessException("名称不能为空");
            }

            BusinessDTO paramName = new BusinessDTO();
            paramName.setName(businessDTO.getName());
            paramName.setCategoryId(businessDTO.getCategoryId());
            if (this.selectCount(paramName) > 0) {
                throw new BusinessException("名称[" + businessDTO.getName() + "]已存在");
            }
        }
    }

    public QueryRespBean<BusinessDTO> getPageList(String categoryId, String keyWords, Integer type,
                                                  Integer pageNo, Integer pageSize) {
        if(StringUtils.isBlank(categoryId)){
            categoryId = "0";
        }
        //获取当前主题下的所有子节点
        List<String> catrgoryIds = categoryService.getChildTypeIds(categoryId);

        QueryRespBean<BusinessDTO> queryRespBean = new QueryRespBean<>();
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);
        Page<BusinessDTO> page = this.mapper.getPageList(catrgoryIds, keyWords, type, wordSecretList);
        try {
            valueConvert(page);
        } catch (Exception e) {
            e.printStackTrace();
        }
        queryRespBean.setResult(page);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    private void valueConvert(Page<BusinessDTO> page) {
        //循环组装请求数据
        Map<String, Set<String>> convertFormData = new HashMap<>(16);
        for (BusinessDTO businessDTO : page) {
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, businessDTO.getCreatedBy());
            BusinessUtil.createConvertSet(convertFormData, Constants.BDP_DATA_SECRET_LEVEL_KEY, businessDTO.getSecretLevel());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            //循环设置Alias或Name的值
            for (BusinessDTO businessDTO : page) {
                businessDTO.setStatusString(StatusEnums.getDescByCode(businessDTO.getStatus()));
                businessDTO.setCreatedBy(BusinessUtil.convertFormat(convertResultData, SystemConstant.USER,
                        businessDTO.getCreatedBy()));
                businessDTO.setSecretLevelName(BusinessUtil.convertFormat(
                        convertResultData, Constants.BDP_DATA_SECRET_LEVEL_KEY, businessDTO.getSecretLevel()));
            }
        }
    }

    /**
     * 查询业务实体树
     * @return
     */
    public List<BdpDasCategoryDTO> findBusinessTree() {
        try {
            List<BdpDasCategoryDTO> dataList = new ArrayList<>();

            List<BdpDasCategoryDTO> categoryList = categoryService.findCategoryTreeByStatus();
            List<BusinessDTO> businessList = this.mapper.selectListByType(0);
            if (businessList != null && businessList.size() > 0) {
                for (BusinessDTO businessDTO : businessList) {
                    BdpDasCategoryDTO business = new BdpDasCategoryDTO();
                    business.setParentId(businessDTO.getCategoryId());
                    business.setId(businessDTO.getId());
                    business.setName(businessDTO.getName());
                    business.setTableFlag(1);
                    dataList.add(business);
                }
            }

            Map<String, List<BdpDasCategoryDTO>> typeTableMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(dataList)) {
                for (BdpDasCategoryDTO categoryDTO : dataList) {
                    if (categoryDTO == null || StringUtils.isBlank(categoryDTO.getParentId())) {
                        continue;
                    }

                    if (!typeTableMap.containsKey(categoryDTO.getParentId())) {
                        List<BdpDasCategoryDTO> child = new ArrayList<>();
                        child.add(categoryDTO);
                        typeTableMap.put(categoryDTO.getParentId(), child);
                        continue;
                    }

                    List<BdpDasCategoryDTO> child = typeTableMap.get(categoryDTO.getParentId());
                    child.add(categoryDTO);
                }
            }

            recursiveSetTable(categoryList, typeTableMap);

            return categoryList;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 递归设置主题节点下的业务对象列表
     *
     * @param categoryList
     * @param typeTableMap
     */
    private void recursiveSetTable(List<BdpDasCategoryDTO> categoryList, Map<String, List<BdpDasCategoryDTO>> typeTableMap) {
        if (CollectionUtils.isEmpty(categoryList)) {
            return;
        }

        for (BdpDasCategoryDTO categoryDTO : categoryList) {
            if (categoryDTO.getLeaf() == 1) {
                List<BdpDasCategoryDTO> tableList = typeTableMap.get(categoryDTO.getId());
                if (CollectionUtils.isNotEmpty(tableList)) {
                    categoryDTO.setChildren(tableList);
                }
            } else {
                recursiveSetTable(categoryDTO.getChildren(), typeTableMap);
            }
        }
    }

    public BusinessDTO queryById(String id) {
        BusinessDTO businessDTO = this.mapper.queryById(id);
        CheckParaUtils.checkDbObjectValidity(businessDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", id));

        businessDTO.setStatusString(StatusEnums.getDescByCode(businessDTO.getStatus()));
        return businessDTO;
    }

    public void updateStatus(String ids, Integer status) {
        CheckParaUtils.checkStringValidity(ids, logger, "没有传入待启用/停用的ID");
        String[] idArr = ids.split(Constants.COMMA);
        for (String id : idArr) {
            BusinessDTO businessDTO = this.selectByPrimaryKey(id);
            CheckParaUtils.checkDbObjectValidity(businessDTO, logger, String.format("没有查到数据，请确保id:%s的资源分层是否存在", id));

            // 修改状态
            businessDTO.setStatus(status);

            String logTitle = "";
            if (status == 0) {
                logTitle = "停用业务对象：【";
            } else {
                logTitle = "启用业务对象：【";
            }
            logTitle += businessDTO.getName() + "】";
            BdpLogUtil.log("业务对象模块", logTitle, PlatformConstant.OpType.update);
            this.updateByPrimaryKeySelective(businessDTO);
        }
    }

    public Map<String, Object> searchBusinessImage(String categoryId) {
        Map<String, Object> map = Maps.newHashMap();
        List<String> businessIds = Lists.newArrayList();
        // 查询主题下的业务对象
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        List<BusinessDTO> businessDTOS = this.mapper.selectListByCategoryId(categoryId, wordSecretList);
        if (CollectionUtils.isEmpty(businessDTOS)) {
            return null;
        } else {
            for (BusinessDTO businessDTO : businessDTOS) {
                businessIds.add(businessDTO.getId());
            }
        }
        List<BdpDasBusinessLinkDTO> linkDTOList = bdpDasBusinessLinkService.searchLinkByBusinessId(businessIds);
        map.put("businessList", businessDTOS);
        map.put("linkList", linkDTOList);
        return map;
    }

    public void updatePosition(BusinessDTO businessDTO) {
        BusinessDTO oldBusinessDTO = this.selectByPrimaryKey(businessDTO.getId());
        CheckParaUtils.checkDbObjectValidity(oldBusinessDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", businessDTO.getId()));

        oldBusinessDTO.setBusinessX(businessDTO.getBusinessX());
        oldBusinessDTO.setBusinessY(businessDTO.getBusinessY());
        this.updateByPrimaryKey(oldBusinessDTO);
        BdpLogUtil.log4Update(businessDTO, oldBusinessDTO);
    }
}
